import { CCInteger, UIOpacity } from "cc";
import { Renderable2D } from "cc";
import { Color, Node, Enum, color, _decorator } from "cc";
import c3d from "../../cc";
import { ProxyOb } from "./Core/ProxyOb";
import VmBase from "./Core/VmBase";

/*
 * @features: 功能
 * @description: 说明
 * @Date: 2021-09-07 22:23:11
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2021-10-03 14:04:59
 * @LastEditors: judu233
 */
const { ccclass, property, menu } = _decorator;
/**比较条件 */
enum CONDITION {
    "==", //正常计算，比较 等于
    "!=", //正常计算，比较 不等于
    ">",  //正常计算，比较>
    ">=", //正常计算，比较>=
    "<",  //正常计算，比较<
    "<=", // 正常计算，比较>=
    "range" //计算在范围内
}
enum ACTION {
    节点激活_不满足不激活, //满足条件 的 节点激活 ，不满足的不激活
    节点显示_不满足不显示, //满足条件 的节点显示，不满足的不显示
    改变不透明度_不满足255,  //满足条件的节点改变不透明度，不满足的还原255
    改变节点颜色_不满足白色, //满足条件的节点改变颜色，不满足的恢复白色
    自定义组件激活, //自定义控制组件模式
}
enum CHILD_MODE_TYPE {
    节点排序,
    节点名字
}

@ccclass(`VmStateParme`)
class VmStateParme {

    @property({ displayName: `遍历子节点判断`, tooltip: '遍历子节点,根据子节点的名字或名字转换为值，判断值满足条件 来激活', })
    foreachChildMode: boolean = false;

    @property({ displayName: `满足判断`, type: Enum(CONDITION), })
    condition: CONDITION = CONDITION["=="];

    @property({ displayName: `判断类型`, tooltip: '遍历子节点,根据子节点的名字转换为值，判断值满足条件 来激活', type: Enum(CHILD_MODE_TYPE), visible(this: VmStateParme) { return this.foreachChildMode } })
    foreachChildType: CHILD_MODE_TYPE = CHILD_MODE_TYPE.节点排序;

    @property({ displayName: '判断值A', visible(this: VmStateParme) { return !this.foreachChildMode }, })
    valueA: number = 0;
    @property({ displayName: '判断值B', visible(this: VmStateParme) { return !this.foreachChildMode && this.condition === CONDITION.range } })
    valueB: number = 0;


    @property({ displayName: `通过执行操作`, tooltip: '一旦满足条件就对节点执行操作', type: Enum(ACTION) })
    valueAction: ACTION = ACTION.节点激活_不满足不激活;

    @property({ displayName: 'opacity改变', visible: function () { return this.valueAction === ACTION.改变不透明度_不满足255 }, range: [0, 255], type: CCInteger, })
    valueActionOpacity: number = 0;

    @property({ displayName: 'Color改变', visible: function () { return this.valueAction === ACTION.改变节点颜色_不满足白色 }, })
    valueActionColor: Color = color(155, 155, 155);

    @property({ displayName: '组件名', visible: function () { return this.valueAction === ACTION.自定义组件激活 }, })
    valueComponentName: string = '';

    @property({ displayName: '组件属性', visible: function () { return this.valueAction === ACTION.自定义组件激活 }, })
    valueComponentProperty: string = '';

    @property({ displayName: '默认值', visible: function () { return this.valueAction === ACTION.自定义组件激活 }, })
    valueComponentDefaultValue: string = '';

    @property({ displayName: '改变值', visible: function () { return this.valueAction === ACTION.自定义组件激活 }, })
    valueComponentActionValue: string = '';

    @property({
        displayName: '执行节点',
        type: [Node],
        tooltip: '需要执行条件的节点，如果不填写则默认会执行本节点以及本节点的所有子节点 的状态',
        visible(this: VmStateParme) { return !this.foreachChildMode; }
    })
    watchNodes: Node[] = [];
}

@ccclass(`VmState`)
@menu('VM/VM-State')
export default class VmState extends VmBase {
    @property(VmStateParme)
    stateSet: VmStateParme = new VmStateParme();

    onEditor() {
        super.onEditor();
        if (this.stateSet.watchNodes.length == 0) {
            //如果数组里没有监听值，那么默认把所有子节点给监听了
            if (this.stateSet.valueAction !== ACTION.节点激活_不满足不激活 && !this.stateSet.foreachChildMode) {
                this.stateSet.watchNodes.push(this.node);
            }
        }
    }

    checkCanWatch() {
        if (!this._checkDataPath()) return false;
        this.parseDataPath();
        return true;
    }

    /**当值初始化时 */
    protected onDataInit() {
        if (this.enabled) {
            if (this.stateSet.foreachChildMode)
                this.stateSet.watchNodes = this.node.children;
            let value = ProxyOb.getValue(this.watch.path);
            this.checkNodeFromValue(value);
        }
    }

    /**当值被改变时 */
    protected onDataChange(newVar: any, oldVar: any, path: string) {
        this.checkNodeFromValue(newVar);
    }

    /**检查节点值更新 */
    private checkNodeFromValue(value) {
        if (this.stateSet.foreachChildMode) {
            this.stateSet.watchNodes.forEach((node, index) => {
                let check = this.conditionCheck(value, (this.stateSet.foreachChildType === CHILD_MODE_TYPE.节点排序) ? index : node.name);
                //cc.log('遍历模式',value,node.name,check);
                this.setNodeState(node, check);
            });
        } else {
            let check = this.conditionCheck(value, this.stateSet.valueA, this.stateSet.valueB);
            this.stateSet.watchNodes.forEach((node) => {
                this.setNodeState(node, check);
            });
        }
    }

    /**更新单个节点的状态 */
    protected setNodeState(node: Node, checkState?: boolean) {
        let n = this.stateSet.valueAction;
        let check = checkState;
        let a = ACTION;
        switch (n) {
            case a.节点激活_不满足不激活:
                node.active = check ? true : false; break;
            case a.节点显示_不满足不显示:
                let opacity = node.getComponent(UIOpacity) ?? node.addComponent(UIOpacity);
                opacity.opacity = check ? 255 : 0; break;
            case a.改变节点颜色_不满足白色:
                let renderable2D = node.getComponent(Renderable2D);
                if (renderable2D) {
                    renderable2D.color = check ? this.stateSet.valueActionColor : color(255, 255, 255);
                }
                break;
            case a.改变不透明度_不满足255:
                opacity = node.getComponent(UIOpacity) ?? node.addComponent(UIOpacity);
                opacity.opacity = check ? this.stateSet.valueActionOpacity : 255; break;
            case a.自定义组件激活:
                let comp = node.getComponent(this.stateSet.valueComponentName);
                if (comp == null) return;
                if (this.stateSet.valueComponentProperty in comp) {
                    comp[this.stateSet.valueComponentProperty] = check ?
                        this.stateSet.valueComponentActionValue : this.stateSet.valueComponentDefaultValue;
                }
                break;
            default: break;
        }
    }

    /**条件检查 */
    private conditionCheck(v, a, b?) {
        let cod = CONDITION;
        switch (this.stateSet.condition) {
            case cod["=="]: return v == a;
            case cod["!="]: return v != a;
            case cod["<"]: return v < a;
            case cod[">"]: return v > a;
            case cod[">="]: return v >= a;
            case cod["<"]: return v < a;
            case cod["<="]: return v <= a;
            case cod["range"]: return v >= a && v <= b;
            default: return false;
        }
    }

}
